Skip to content

Build the Platform Core, Chat, and member integrations UI - #9687

Open
emir-karabeg wants to merge 1746 commits into
stagingfrom
improvement/platform-core-chat
Open

emir-karabeg wants to merge 1746 commits into
stagingfrom
improvement/platform-core-chat

Conversation

@emir-karabeg

@emir-karabeg emir-karabeg commented Nov 4, 2026 •

Copy link
Copy Markdown
Collaborator

Home, Chat, Settings and organization integrations use the shared navigation shell and real routes in the isolated Platform Next.js app. The browser and Sim Desktop share the renderer. A default-off server fixture supplies populated, empty and stress states without a database.

The shared App Router layout owns the sidebar. Selecting a chat, visiting Settings, or reopening the compact drawer preserves the reader’s position. Command K uses the shared menu rows and headings: Home, Settings and Integrations keep their icons, and workspace and chat results are text-only. Search, results and shortcut hints align to one inset, and moving from pointer to keyboard leaves only the active result highlighted.

Home and Chat share a reading column and a Recents component. Home opens recent websites in another tab; dismissal carries into Chat. The activity chart switches between Tasks run and Searches without losing its date range. Widgets and notifications share a height ceiling and scroll independently. Calendar’s Now control returns to the current day and time. Events open an external tab only when a provider supplies a URL; attendees have their own popover.

Navigation, tabs, recents and attachment previews share ControlRow. Invite recipients use compact address tags with an always-visible remove button inside each tag. Form dialogs focus the first available field and restore focus on close. Invite accepts typed and pasted addresses, supports keyboard removal and leaves sending to Phase 3. Chat keeps prose and tool activity aligned, and shares its time formatting and copy feedback with the rest of the Platform.

The member Integrations inventory uses workspace catalog descriptions for each provider. Its detail shows the provider name and description, then one connected credential with its actions menu. The inline connection prompt shares Home’s Email and Calendar styling and links to the Sim Search setup guide. Eligible tool approvals remain individual. Known OAuth permissions are grouped by purpose and always visible. Managed Search providers show their actual read-only operations, including Fireflies meeting search, transcripts, and summaries. The server fixture flag gates all sample connections. Member inventory and operation mapping.

See the component ownership map, Platform contract and Core/Chat source-state inventory. To run locally: SIM_PLATFORM_FIXTURES=1 bun run --cwd apps/sim dev:platform; visit /home?state=full, /chat/weekly-review?state=full /settings?state=full, or /integrations?state=full.

Verification exercises the production Next build, Chromium with fixture-on and fixture-off servers, and the native Electron renderer. Browser journeys measure scroll bounds, hit targets and spacing, exercise keyboard selection and focus return, and distinguish resting/hover/pressed feedback in both themes. The design audit checks ownership, token and variant use, timers, modal chrome and the fixture boundary. It recognizes JSX returned by local render helpers and active route fallbacks. The tracked Platform skill and contract route new work, cleanup and Settings reviews to the correct component library, and distinguish shared preferences from decisions owned by one feature.

Stacked on #9667, which targets staging.

Chat now steers instead of queueing. A message sent during a turn is applied to that turn at its next step, through the worker's durable v2 endpoint (simstudioai/mothership#929, which must deploy first; against an older worker a message waits for the turn's end and goes out as the next turn). If the turn ends without applying it, it goes out once as the next turn under the same id, and the worker refuses it if a run already applied it. The client queue is removed from every chat surface. Undelivered messages show a status line with Retry and Dismiss. Outgoing messages survive a reload through a per-tab journal, and anything past 10 minutes never sends itself. apps/sim/scripts/test-chat-steering-e2e.ts proves this across a real browser, app, worker and database (bun run test:chat-steering:e2e, not wired into CI).

Companion worker change (ships together)

  • simstudioai/mothership#943 — the worker side of this cutover: POST /api/chats/rescope for chats moved out of a retired or reverted personal organization, and personal-organization chats keyed to their member's personal memory graph.
  • Deploy order: merge and deploy mothership#943 first, then this PR. The worker change is backward compatible with the current Sim.

@emir-karabeg
emir-karabeg requested a review from a team as a code owner November 4, 2026 23:24
@vercel

vercel Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
docs Ready Ready Preview Nov 11, 2026 5:52am UTC

Request Review

@greptile-apps

greptile-apps Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 3/5

[Medium impact] The changes reach the standalone Platform’s Home, Chat, and Settings flows on web and Desktop.

Fix the lost Stop control and covered desktop panel tabs before merging.

Findings

  1. P1 Follow-up removes Stop ▶
  2. P1 Toolbar covers panel tabs ▶
  3. P2 Unsent messages disappear ▶
  4. P2 Saved profile edits vanish ▶
  5. P2 Navigation resets shell changes ▶

Summary

Adds standalone Home, Chat and Settings routes for browsers and Sim Desktop, with shared controls, gated fixtures and browser/Electron checks.

  • The Platform opens on Home with shared navigation and a dashboard people can customize.
  • Chat keeps drafts, attachments, and panel interactions local to the Platform session.
  • Settings adds profile, appearance, notification, and member screens to the Platform.
  • Shared controls support the new product routes, and the component workbench has its own route.
  • Build and design checks now cover the Platform product routes and Desktop renderer.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  Layout["Shared ProductSession"] --> Preferences["Interface preferences"]
  Layout --> Changes["Chat edits"]
  Layout --> Page["Home, Chat or Settings page"]
  Page --> Frame["ProductFrame"]
  Frame --> Shell["PlatformShell"]
  Shell --> Local["Inbox, notices and sort state"]
  Shell --> Feature["Feature screen"]
  Feature --> Draft["Local draft or profile edits"]
Loading

Reviews (1) · Last reviewed commit: "feat(platform): build Core and Chat for ..." · Reviewed by Greptile

Comment on lines +102 to +108
onStop={
last?.response?.state === 'running' ? () => transition(last, 'stopped') : undefined
}
onSubmit={(draft) => {
const next = userTurn(draft)
if (id && !removed) {
changes.setTurnsFor(id, [...turns, next])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Follow-up removes Stop

In /chat/customer-onboarding?state=full, pressing Enter on a follow-up appends a user turn while the response is running. onStop then disappears because it checks only the last turn, which now has no response. The earlier response stays “Working” with no way to stop it. Track the running turn separately, or block submission while it is running.

Comment on lines +17 to +24
padding-inline: var(--spacing-12);
min-inline-size: 0;
height: var(--height-nav);
border-block-end: var(--spacing-stroke-default) solid var(--ui-divider);
}
:global([data-sim-desktop-title-bar]) .header {
height: var(--spacing-48);
-webkit-app-region: drag;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Toolbar covers panel tabs

With the desktop sidebar collapsed, expanding the chat panel puts its tabs under the desktop toolbar and native window buttons. The shell places the content at the top-left, but the panel header keeps only 12px of left padding. Unlike the conversation header, it does not use --ui-navigation-inset. Reserve that space when the panel takes over so its first tab and close control remain clickable.

Comment on lines +18 to +19
<ChatPanels workspaces={shell?.workspaces ?? []} data={panel} key={id?.[0] ?? 'new'}>
<ChatScreen data={data?.chat ?? null} chatId={id?.[0]} />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Unsent messages disappear

Switching chats discards unsent text and selected files. MessageComposer keeps both only in local state, while this route keys the whole panel tree by chat ID. Returning to the original chat creates a fresh composer. Keep drafts in the session, keyed by chat ID, so ordinary navigation does not erase unfinished messages.

Comment on lines +20 to +21
const [displayName, setDisplayName] = useState(name ?? '')
const [picture, setPicture] = useState<string>()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Saved profile edits vanish

Saving a display name or choosing a profile picture lasts only until the user leaves Preferences. ProfileSettings owns these values locally and is removed on other Settings sections. Returning restores the fixture name and drops the picture. Keep these local edits in the session provider; no database write is needed.

Comment on lines +30 to +33
<ProductSurface preference={appearance}>
<PlatformShell data={shell} desktopTitle={desktopTitle} navigation={navigation}>
{children}
</PlatformShell>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Navigation resets shell changes

Each page creates its own PlatformShell, so moving between Home, Chat and Settings resets inbox read marks, dismissed notices and chat sorting. For example, reading an unread item, opening a chat and returning makes that item unread again. Move this session state above the page boundary, alongside the existing chat edits and interface preferences.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 issues found and verified against the latest diff

Confidence score: 3/5

  • In chat-screen.tsx, submitted attachments can reappear in the new chat when changing the chat ID remounts the composer. Clear the attachment draft when the send succeeds.
  • In workspace-list.tsx, keyboard users get no visible focus indicator on workspace buttons. Add a :focus-visible treatment.
  • In product-surface.tsx, users with a dark system theme can see a light flash before hydration. Resolve the system theme before first paint.
  • In notification-tray.module.css, notification controls can sit under the home indicator on notched mobile browsers. Account for the bottom safe-area inset.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/sim/platform/design-system/components/workspace-list.tsx">

<violation number="1" location="apps/sim/platform/design-system/components/workspace-list.tsx:43">
P2: This new keyboard-focusable workspace button has no visible focus indicator because the global stylesheet removes outlines and `.workspaceHit` adds none. Add a shared or workspace-specific `:focus-visible` treatment so keyboard users can identify the active row.</violation>
</file>

<file name="apps/sim/platform/design-system/components/product-surface.tsx">

<violation number="1" location="apps/sim/platform/design-system/components/product-surface.tsx:10">
P2: System appearance always renders light on the server, causing dark-system users to see a light flash before hydration applies the media-query result. Resolve the system theme before first paint, such as with a CSS media-query path plus explicit-theme override or a small theme bootstrap.</violation>
</file>

<file name="apps/sim/platform/design-system/components/select.tsx">

<violation number="1" location="apps/sim/platform/design-system/components/select.tsx:37">
P2: An arbitrary `theme` query can reach this controlled value without matching any option, so the Theme picker renders blank even though the surrounding product falls back to `system`. Ignore values outside `options` here or pass the normalized theme from the settings screen.</violation>
</file>

<file name="apps/sim/platform/design-system/features/chat/chat-screen.tsx">

<violation number="1" location="apps/sim/platform/design-system/features/chat/chat-screen.tsx:100">
P2: The first send from `/chat` clears the composer only until `router.replace` changes `id`; this prop then remounts `MessageComposer` with the unchanged draft attachments, so submitted files reappear in the new chat’s composer. Track and consume the initial draft when submitting before navigation.</violation>
</file>

<file name="apps/sim/platform/design-system/components/notification-tray.module.css">

<violation number="1" location="apps/sim/platform/design-system/components/notification-tray.module.css:10">
P2: The fixed notification stack ignores the bottom safe-area inset, so its action and dismiss controls can sit under the home indicator on notched mobile browsers. Use `max(var(--spacing-20), env(safe-area-inset-bottom))` for the bottom offset.

(Based on your team's feedback about toast safe-area minimum.) [8c7692a3-398e-4004-b266-f2a76922d36c]</violation>
</file>

Reply with feedback, questions, or to request a fix.

Turn on auto-fix | Re-trigger cubic

Comment thread apps/sim/platform/app/layout.tsx Resolved
@emir-karabeg emir-karabeg changed the title Build the Core and Chat UI for web and Sim Desktop Build the Platform Core, Chat, and organization integrations UI Nov 5, 2026
@emir-karabeg emir-karabeg changed the title Build the Platform Core, Chat, and organization integrations UI Build the Platform Core, Chat, and member integrations UI Nov 5, 2026
@waleedlatif1
waleedlatif1 force-pushed the improvement/platform-core-chat branch from 6133099 to 8d35586 Compare November 5, 2026 06:55
…iring

# Conflicts:
#	apps/sim/lib/credentials/service-account-secret.ts
… blocks on the shared settings parts

API keys: one Manage section holds New API key and the personal-keys SwitchRow, each list is a
SettingsList, the read is SettingsRead, and Copy name is gone. BYOK opens a provider's keys as a
sub-view through useSettingsSubview, with the key form's draft inside its dialog. Custom tools and
custom blocks open their create flow through useSettingsSubview, end their list with a New row,
commit edits through SettingsSaveBar and delete from a Manage section. The custom block editor
splits into Source, Inputs and Outputs and no longer sets state during render.
The sync detail commits mapping edits through SettingsSaveBar, the fork and activity sub-views open
through useSettingsSubview, Forks and Events are SettingsLists, the synced-workflow tree opens
collapsed, and undoing a sync reads Undo last sync from button to confirm.
…ention, data drains, audit logs and access control
The task list pages through the inbox's cursor with the shared load-more and no longer echoes the
search; the address is one row with Change address; members collapse into one summary row; each
dialog holds its own draft; the enable switch is a SwitchRow; and the disable confirm says what
actually happens: the address is deleted, and turning the inbox back on makes a new one.
…red switch rows, and Knowledge graphs as a form dialog

The route picks the live or session profile, theme row and cookie choices, so
the views stay prop-driven. Profile accepts the picture types it validates.
Account loses the Home page row and its duplicate anonymous guard. Privacy keeps
its sub-view, since hosted adds the cookie choices; its rows are SwitchRows and
the cookie note is Muted. The consent banner's switches are SwitchRows.
Knowledge graphs reads its name from a form Modal, which owns pending, and its
section no longer repeats the page title.
The page reads the request's user agent on the server, so macOS shows ⌘⇧P and
others Ctrl+Shift+P, with no hydration flip. Shortcut rows keep no description
by design: the label names the action and the keys are its value. The DOM test
restated the list and the hard-coded key strings; the Record over CommandId
already fails type-check for an unlisted command.
…and one theme vocabulary

Desktop: every toggle through useDesktopPreferenceMutation and SwitchRow, the
device read folded into the page's one read, Computer use below the device
settings with its running action still on top, Allowed as a StatusTag, approved
apps as a query, and a menu-bar row that says what it does.
Browser: one Clear browsing data row whose dialog says what it clears, saved
passwords read only on the Passwords view through a query, the open password in
the URL, Delete for every removal, and confirms that fail in their dialog
instead of reading a missing bridge as success.
Terminal: its section named for the page's one job, SwitchRow, Preferences in
the TSDoc. Browser, Terminal and the terminal panel share Match Sim, Light and
Dark. Drops the migrated pages' allowlist entries.
… settings parts

The MCP list reads each server's stored tool count instead of discovering every server's tools, and
opening a server, by a click or a shared link, re-discovers that server alone through a probe query
its detail mounts, which replaces the ref-guarded deep-link effect. Both MCP pages open servers
through useSettingsSubview, list them in a SettingsList that ends in a New row, delete from a
Manage section, and drop counts from headings and the repeated server name. Deployed workflows load
only while the create dialog is open.
…ed on the shared settings parts

The sandbox editor owns its draft and mutations, keyed by the sandbox it opened, which retires the
draft-owner state set during render and the eighteen drilled props; create opens through
useSettingsSubview and submits through Create sandbox, edits through SettingsSaveBar. Teammates
lists members and invites under one SettingsList ending in Invite teammates, whose button is
disabled with its reason, or reads View plans where a plan limit closes it. Recently deleted merges
restored rows without splicing during render and labels types in sentence case.
…arts

Members: SectionStack and SettingsList in place of a local panel and EmptyState
inside a surface, no counts in headings, Invite's disabledReason, confirm titles
that name the object.

Billing and Insights share one PeriodPicker (no getElementById focus hack) and one
UsageLedger with Export in its header; the export busy flag resets in finally.
Credit usage is gated on the server instead of an effect redirect. Invoices are a
ResourceList of ActivityRows; Manage in Stripe is the one portal action. On-demand
uses SwitchRow with the lock reason in its description.

Insights: the heatmap fits the column without a ScrollArea (narrow widths drop the
oldest weeks through a container query), one UsageBlock replaces three hand-built
sections, the toolbar is SectionToolbar, Activity's workspace drill-in uses
DetailHeader, and the activity summary lives on Activity only.
… pager

People pages in the browser through an infinite query seeded by the server read,
ending in LoadMoreFooter, in place of a client slice plus a server Next page; the
view no longer filters what the read already matched. Removing a workspace's
access is a row menu Remove behind ConfirmDialog, and its 1000-workspace limit is
a model constant. The provider icon mapping moves into the model, the tab strip
is no longer wrapped in an ActionRow, and the lists drop the headings that
repeated their tab. Searches carry placeholders and show only with rows to
search; empty lists are EmptyStates outside the surface with their create action.
… the shared parts

Whitelabeling commits through SettingsSaveBar, which now owns its leave guard.
Recently deleted: Restoring…, a placeholder with …, no search with nothing
deleted, SectionStack. Requests: SwitchRow for Allow requests, one toolbar of
search and status filter by the list, a plain Requests heading. Links: one
SectionToolbar (bordered search, Sort, New link), no second New link in the empty
state, the table's default viewport offset instead of hand arithmetic, and the
name cell and row menu split into their own files. Drops the migrated pages'
allowlist entries.
# Conflicts:
#	scripts/platform-allowlists.ts
The secrets editor splits into GenericSecrets, WorkspaceSecrets, SecretRows and the row cells, commits
through SettingsSaveBar, and shows an empty scope as a SettingsList empty state with Add secret
instead of a blank row under a disabled Save. A secret's detail and its usage view open through
useSettingsSubview (?secret=, ?secret-view=), so the secrets section no longer declares a path
subpath; the detail drops the repeated Key field, its visibility switch is a SwitchRow, and the
credential form leaves the leave guard to the save bar.
# Conflicts:
#	scripts/platform-allowlists.ts
…RL tabs, shared parts on SCIM, admin, Mothership, Search MCP and Slack
# Conflicts:
#	scripts/platform-allowlists.ts
@blacksmith-sh

blacksmith-sh Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

Found 10 test failures on Blacksmith runners:

Failures

Test View Logs
[product] › platform/checks/live/
links.spec.ts:42:5 › Links: header, Chrome install, columns, and a list that reads on a
s it scrolls
View Logs
[product] › platform/checks/live/
routes.spec.ts:160:9 › settings-privacy renders healthy in both themes at both widths
View Logs
[product] › platform/checks/live/
routes.spec.ts:160:9 › settings-usage-events renders healthy in both themes at both wid
ths
View Logs
[product] › platform/checks/live/
settings-a.spec.ts:111:5 › a plan read on the server stands when the browser’s own read
fails
View Logs
[product] › platform/checks/live/
settings-b.spec.ts:89:7 › governance settings › single sign-on never receives a stored
client secret
View Logs
governance settings/single sign-on never receives a stored client secret View Logs
platform/checks/live/links.spec.ts/
Links: header, Chrome install, columns, and a list that reads on as it scrolls
View Logs
platform/checks/live/routes.spec.ts/
settings-privacy renders healthy in both themes at both widths
View Logs
platform/checks/live/routes.spec.ts/
settings-usage-events renders healthy in both themes at both widths
View Logs
platform/checks/live/settings-a.spec.ts/
a plan read on the server stands when the browser’s own read fails
View Logs

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

…iring

# Conflicts:
#	.agents/skills/add-block/SKILL.md
#	apps/sim/components/integrations/connect-service-account-modal/google-keyless-fields.tsx
#	apps/sim/components/integrations/connect-service-account-modal/snowflake-account-modal.tsx

This branch was successfully deployed

1 active deployment
Preview — bca74ad3 Deployed Nov 11, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

requires-mothership-merge Has a companion PR on the mothership/copilot side — merge in lockstep

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants